package com.ruoyi.cm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.ruoyi.base.domain.BaseBsFbfx;
import com.ruoyi.base.domain.BaseBsZd;
import com.ruoyi.base.mapper.BaseBsFbfxMapper;
import com.ruoyi.base.mapper.BaseBsZdMapper;
import com.ruoyi.cm.domain.*;
import com.ruoyi.cm.domain.bo.CmBdQsCountBo;
import com.ruoyi.cm.domain.vo.ReportVo;
import com.ruoyi.cm.mapper.*;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.service.ConfigService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.BigDecimalUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.wecom.client.WeComUtils;
import com.ruoyi.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.flowable.engine.HistoryService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.stereotype.Service;
import com.ruoyi.cm.domain.bo.CmReportBo;
import com.ruoyi.cm.domain.vo.CmReportVo;
import com.ruoyi.cm.service.ICmReportService;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static org.apache.poi.ss.util.DateParser.parseLocalDate;

/**
 * 报管理Service业务层处理
 *
 * @author zxs
 * @date 2024-10-09
 */
@RequiredArgsConstructor
@Service
public class CmReportServiceImpl implements ICmReportService {

    private final CmReportMapper baseMapper;
    private final CmBsQsMapper qsMapper;
    private final CmBsProcessInspectionMapper processInspectionMapper;
    private final CmBsProcessMapper processMapper;
    private final BaseBsZdMapper zdMapper;
    private final CmBdQsCountMapper countMapper;
    private final BaseBsFbfxMapper fbfxMapper;
    private final CmBdQsCountServiceImpl countService;
    //合同里程碑；
    private final CmBsContractInfoMilestoneMapper milestoneMapper;
    //合同信息；
    private final CmBsContractInfoMapper contractMapper;
    private final TaskService taskService;
    private final ISysUserService userService;
    private final ConfigService configService;
    @Resource
    protected HistoryService historyService;

    private final static String GXBY_TIME_KEY = "gx.time";
    private final static String ERROR_MESSAGE = "以下站点工序报验审批流程没有审批完成，不允许发起审批：";
    /**
     * 查询报管理
     */
    @Override
    public CmReportVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询报管理列表
     */
    @Override
    public TableDataInfo<CmReportVo> queryPageList(CmReportBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<CmReport> lqw = buildQueryWrapper(bo);
        Page<CmReportVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询报管理列表
     */
    @Override
    public List<CmReportVo> queryList(CmReportBo bo) {
        LambdaQueryWrapper<CmReport> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<CmReport> buildQueryWrapper(CmReportBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<CmReport> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getBdId() != null, CmReport::getBdId, bo.getBdId());
        lqw.eq(bo.getQsId() != null, CmReport::getQsId, bo.getQsId());
        lqw.eq(bo.getZdId() != null, CmReport::getZdId, bo.getZdId());
        lqw.eq(bo.getStatus() != null, CmReport::getStatus, bo.getStatus());
        lqw.eq(bo.getQs() != null, CmReport::getQs, bo.getQs());
        lqw.eq(ObjectUtils.isNotEmpty(bo.getRatio()), CmReport::getRatio, bo.getRatio());
        lqw.eq(ObjectUtils.isNotEmpty(bo.getProcInsId()), CmReport::getProcInsId, bo.getProcInsId());
        return lqw;
    }

    /**
     * 新增报管理
     */
    @Override
    public Boolean insertByBo(CmReportBo bo) {
        CmReport add = BeanUtil.toBean(bo, CmReport.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改报管理
     */
    @Override
    public Boolean updateByBo(CmReportBo bo) {
        CmReport update = BeanUtil.toBean(bo, CmReport.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(CmReport entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除报管理
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public CmReport getInfo(CmReportBo bo) {

        LambdaQueryWrapper<CmReport> lqw = buildQueryWrapper(bo);
        List<CmReport> reports = baseMapper.selectList(lqw);
        CmReport report = null;
        if(CollUtil.isNotEmpty(reports)){
            reports = reports.stream().filter(e -> e.getZdId() == null).collect(Collectors.toList());
            if(CollUtil.isNotEmpty(reports)){
                report = reports.get(0);
            }
        }
        // 根据procInsId获取taskId
        if (report == null) {
            report = new CmReport();
            report.setBdId(bo.getBdId());
            report.setQsId(bo.getQsId());
            report.setQs(bo.getQs());
            //未审批
            report.setStatus("00");
            baseMapper.insert(report);
        }
        // 审批信息
        if (ObjectUtils.isNotEmpty(report)) {
            if (ObjectUtils.isNotEmpty(report.getProcInsId())) {
                Task task = taskService.createTaskQuery().processInstanceId(report.getProcInsId()).singleResult();
                if (task != null) {
                    report.setTaskId(task.getId());
                    if (task.getAssignee() != null && (Long.valueOf(task.getAssignee()) == LoginHelper.getUserId())) {
                        report.setCurrApproval(true);
                    } else {
                        report.setCurrApproval(false);
                    }
                }
            }
        }
        return report;
    }

    @Override
    public void updateStatusByBo(CmReportBo bo) {
        //如果流程为发起，持久化报表数据；如果为驳回，则将持久化的数据删除；
        if ("33".equals(bo.getStatus())) {
            List<BaseBsZd> zdList = zdMapper.selectList(new LambdaQueryWrapper<BaseBsZd>().eq(BaseBsZd::getBdId, bo.getBdId()));
            Set<Long> zdIds = zdList.stream().map(BaseBsZd::getId).collect(Collectors.toSet());
            baseMapper.delete(new LambdaQueryWrapper<CmReport>().eq(CmReport::getBdId, bo.getBdId()).eq(CmReport::getQsId, bo.getQsId()).in(CmReport::getZdId, zdIds));
        } else if("11".equals(bo.getStatus())) {
            CmBdQsCountBo qsCountBo = new CmBdQsCountBo();
            qsCountBo.setZdId(bo.getZdId());
            qsCountBo.setQsId(bo.getQsId());
            List<ReportVo> reportInfos = countService.getReportInfo(qsCountBo);
            List<CmReport> cmReports = new ArrayList<>();
            for (ReportVo reportVo : reportInfos) {
                CmReport report = new CmReport();
                BeanUtil.copyProperties(reportVo, report);
                cmReports.add(report);
            }
            baseMapper.insertBatch(cmReports);
        }
        //更新期数的结束日期；
        if("22".equals(bo.getStatus())){
            CmBsQs qs = new CmBsQs();
            qs.setQsId(bo.getQsId());
            qs.setSettleEndDate(new Date());
            qsMapper.updateById(qs);
        }
        LambdaUpdateWrapper<CmReport> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(bo.getBdId() != null, CmReport::getBdId, bo.getBdId());
        wrapper.eq(bo.getQsId() != null, CmReport::getQsId, bo.getQsId());
        wrapper.set(bo.getStatus() != null, CmReport::getStatus, bo.getStatus());
        wrapper.set(bo.getProcInsId() != null, CmReport::getProcInsId, bo.getProcInsId());
        baseMapper.update(null, wrapper);
    }

    /**
     *   时间节点参数；
     *  时间节点内各站点对应付款比例的工序报验审批流程是否已完成，没完成，不允许发起审批；
     *
     * @param reportBo
     * @return
     */

    @Override
    public int check(CmReportBo reportBo) {

        //获取时间节点参数配置；
        LocalDate inputDate = null;
        try {
            inputDate = parseLocalDate(configService.getConfigValue(GXBY_TIME_KEY));
        } catch (EvaluationException e) {
            e.printStackTrace();
        }
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        if(currentDate.isAfter(inputDate)){
            //校验各站点对应工序报验审批流程；

        }
        //1、上期审批已完成校验；
//        List<CmBsQs> qsList = qsMapper.selectList(new LambdaQueryWrapper<CmBsQs>().eq(CmBsQs::getBdId, reportBo.getBdId()));
//        Map<Long, CmBsQs> qsMilestoneMap = qsList.stream().collect(Collectors.toMap(CmBsQs::getQsId,e->e));
//        Long milestoneId = qsMilestoneMap.get(reportBo.getQsId()).getContractMilestone();
//        int qs = qsMilestoneMap.get(reportBo.getQsId()).getSettleIndex();
//        //如果不是第一期，校验上期是否已审批完成；
//        if(qs != 1){
//            Set<Long> qsIdSet = qsList.stream().filter(e -> e.getSettleIndex() < qs).map(CmBsQs::getQsId).collect(Collectors.toSet());
//            List<CmReport> cmReports = baseMapper.selectList(new LambdaQueryWrapper<CmReport>().in(CmReport::getQsId, qsIdSet));
//            for(CmReport report : cmReports){
//                if(!StringUtils.equals(report.getStatus(),"22")){
//                    throw new ServiceException("上期报表未审批完成，不允许发起审批");
//                }
//            }
//        }
        return 99;
    }

    /**
     * 校验各站点对应工序报验是否已全部审批完成；
     * @param vos
     * @return
     */
    @Override
    public int checks(List<ReportVo> vos) {
        //获取时间节点参数配置；
        LocalDate inputDate = null;
        try {
            String gxTime = configService.getConfigValue(GXBY_TIME_KEY);
            if(StringUtils.isBlank(gxTime)){
                return 99;
            }
            inputDate = parseLocalDate(gxTime);
        } catch (EvaluationException e) {
            e.printStackTrace();
        }
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        if (currentDate.isAfter(inputDate)) {
            //校验各站点对应工序报验审批流程；
            vos = vos.stream().filter(e -> e.getFukbl() != null && e.getFukbl().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(vos)) {
                StringBuffer sb = new StringBuffer("");
                String s = "";
                Set<Long> zdIds = vos.stream().map(ReportVo::getZdId).collect(Collectors.toSet());
                //根据站点Id查询分部分项；
                List<BaseBsFbfx> fbfxes = fbfxMapper.selectList(new LambdaQueryWrapper<BaseBsFbfx>().in(BaseBsFbfx::getZdId, zdIds));
                if (CollUtil.isEmpty(fbfxes)) {
                    for (ReportVo vo : vos) {
                        sb = sb.append(vo.getName()).append("、");
                    }
                    s = sb.toString();
                    throw new ServiceException(ERROR_MESSAGE + s.substring(0, s.length() - 1));
                }
                Set<Long> fbfxIds = fbfxes.stream().map(BaseBsFbfx::getId).collect(Collectors.toSet());
                //根据站点Id，分部分项Id查询工序报验列表；
                List<CmBsProcessInspection> processInspections = processInspectionMapper.selectList(new LambdaQueryWrapper<CmBsProcessInspection>()
                    .in(CmBsProcessInspection::getZdId, zdIds).in(CmBsProcessInspection::getFbfxId, fbfxIds));
                if (CollUtil.isEmpty(processInspections)) {
                    throw new ServiceException(ERROR_MESSAGE + s.substring(0, s.length() - 1));
                }
                sb = new StringBuffer("");
                s = "";
                //有对应工序报验，
                Map<Long, List<CmBsProcessInspection>> zdProcessMap = processInspections.stream().collect(Collectors.groupingBy(CmBsProcessInspection::getZdId));
                //查询基础工序；获取基础工序的付款范围；
                List<CmBsProcess> bsProcesses = processMapper.selectList();
                Map<Long, String> processIdPayMap = bsProcesses.stream().filter(e -> e.getPaymentRatio2() != null).collect(Collectors.toMap(CmBsProcess::getId, CmBsProcess::getPaymentRatio2));
                for (ReportVo vo : vos) {
                    BigDecimal fukbl = BigDecimalUtil.multiply(vo.getFukbl(),BigDecimal.valueOf(100));
                    List<CmBsProcessInspection> inspections = zdProcessMap.get(vo.getZdId());
                    if (CollUtil.isEmpty(inspections)) {
                        sb.append(vo.getName()).append("、");
                        continue;
                    }
                    //获取所有付款范围小于报表的付款比例的工序报验；审批状态不为已审批；
                    List<CmBsProcessInspection> inspectionList = inspections.stream()
                        .filter(e -> fukbl.compareTo(new BigDecimal(processIdPayMap.get(e.getProcessId()) == null ? "100" : processIdPayMap.get(e.getProcessId()))) >= 0)
                        .filter(e -> !"22".equals(e.getApproveStatus())).collect(Collectors.toList());
                    if (CollUtil.isNotEmpty(inspectionList)) {
                        sb.append(vo.getName()).append("、");
                    }
                }
                if (sb.length() > 1) {
                    s = sb.toString();
                    throw new ServiceException(ERROR_MESSAGE + s.substring(0, s.length() - 1));
                }
            }
        }
        return 99;
    }
}
